#!/usr/bin/python
# -*- coding: UTF-8 -*- 
# 设置utf-8  显示中文
"""
@Create Time: 2020-6-6 13:02
@Author: guo 
@File：get_yml_data.py
"""
import inspect
import sys, os
import yaml

sys.path.append("../../")
from config.get_conf_data import GetConfData

yml_abs_dir = GetConfData().get_ymlfile_abspath()

class GetYmlData:


    def get_yml_dir(self):
        '''返回yml文件所在的目录路径'''
        return yml_abs_dir

    def get_first_call_yml_data(self,yml_dir=None)->dict:
        '''
        返回第一层调用者的调用函数/方法对应的yml的数据,不适用于pytest的parametrize  \n
        :param yml_dir: case或function 对应的yml文件所对应的目录,不包括yml文件的"根"目录data
        :return: 第一层调用者对应的yml文件数据 dict类型
        '''
        # 方法二：
        '''
        如果是在Base.py文件中 调用的话，那么就要使用第二层调用者的函数名和py文件名
        '''
        base = inspect.stack()
        # 当前的函数名
        self_func_name = base[0].function
        # print('当前的函数名为：', self_func_name)
        # 当前文件的py名
        self_py_name = base[0].filename
        # print('当前文件的py名为：', self_py_name)
        # 第一层调用者的函数名
        first_call_func_name = base[1].function
        # print('第一层调用者的函数名为：', first_call_func_name)
        # 第一层调用者的py文件名
        first_call_py_name = base[1].filename
        # print('first_call_py_name is:', first_call_py_name)
        first_call_py = os.path.basename(first_call_py_name)
        # print('第一层调用者的py文件名：', first_call_py)
        # 设置第一层调用者对应的yml的文件名(不含路径)
        first_call_yml = first_call_py.replace('.py', '.yml')
        # 拼接第一层调用者对应的yml的路径(含文件名)
        if yml_dir == None:
            first_yml_path = os.path.join(yml_abs_dir, first_call_yml)
        else:
            first_yml_path = os.path.join(os.path.join(yml_abs_dir,yml_dir),first_call_yml)

        with open(first_yml_path, mode='r', encoding='utf-8')as f:
            yml_datas = yaml.safe_load(f)
            call_yml_data = yml_datas.get(first_call_func_name)

        # # 返回第一层调用者所对应的所有的yml数据
        # return yml_datas
        # # 返回第一层调用者中调用方法所涉及到的yml数据
        return call_yml_data
        # # 将所有的结果都返回了
        # return yml_datas,call_yml_data

    def get_parametrize_yml_data(self, case_method_name: str):
        '''
        返回case对应的yml数据，用于pytest.mark.parametrize()参数化  \n
        需要注意的是在使用pytest.mark.parmaetrize()进行调用时，必须为第一层调用者,  \n
        不能进行嵌套调用，否则无效  \n
        :param case_method_name: case 方法的名称
        :return:
        '''
        '''
        至于为什么要传入case的名称，是因为第一层调用者的函数名为当前的class的名称，而不是case名称。
        所以要传入函数的名称。
        '''
        # 方法二：
        '''
        如果是在Base文件中 调用的话，那么就要使用第二层调用者的函数名和py文件名
        '''
        base = inspect.stack()
        # 当前的函数名
        self_func_name = base[0].function
        # 当前文件的py名
        self_py_name = base[0].filename
        # # 第一层调用者的函数名
        # first_call_func_name = base[1].function
        # 接收case名称
        case_name = case_method_name
        # 第一层调用者的py文件名
        first_call_py_name = base[1].filename
        first_call_py = os.path.basename(first_call_py_name)
        # 设置第一层调用者对应的yml的文件名(不含路径)
        first_call_yml = first_call_py.replace('.py', '.yml')
        # 拼接第一层调用者对应的yml的路径(含文件名)
        first_yml_path = os.path.join(yml_abs_dir, first_call_yml)

        with open(first_yml_path, mode='r', encoding='utf-8')as f:
            yml_datas = yaml.safe_load(f)
            # call_yml_data = yml_datas.get(first_call_func_name)
            call_yml_data = yml_datas.get(case_name)

        # # 返回第一层调用者所对应的所有的yml数据
        # return yml_datas
        # # 返回第一层调用者中调用方法所涉及到的yml数据
        return call_yml_data
        # # 将所有的结果都返回了
        # return yml_datas,call_yml_data

    def get_second_call_yml_data(self):
        '''返回第二层调用者的调用函数/方法对应的yml的数据'''
        # 方法二：
        '''
        如果是在Base.py文件中 调用的话，那么就要使用第二层调用者的函数名和py文件名
        '''
        base = inspect.stack()
        # 第二层调用者的函数名
        second_call_func_name = base[2].function
        # 第二层调用者的py文件名
        second_call_py_name = base[2].filename
        second_call_py = os.path.basename(second_call_py_name)
        # 设置第二层调用者对应的yml的文件名(不含路径)
        second_call_yml = second_call_py.replace('.py', '.yml')
        # 拼接第二层调用者对应的yml的路径(含文件名)
        second_yml_path = os.path.join(yml_abs_dir, second_call_yml)

        with open(second_yml_path, mode='r', encoding='utf-8')as f:
            yml_datas = yaml.safe_load(f)
            call_yml_data = yml_datas.get(second_call_func_name)

        # # 返回第二层调用者所对应的所有的yml数据
        # return yml_datas
        # # 返回第二层调用者中调用方法所涉及到的yml数据
        return call_yml_data
        # # 将所有的结果都返回了
        # return yml_datas,call_yml_data

    def get_yml_data_by_call(self, call_num: int):
        '''
        返回指定层调用者的调用函数对应的yml数据  \n
        :param call_num: 第几层调用者,整数
        :return: 
        '''
        # 方法二：
        '''
        如果是在Base.py文件中 调用的话，那么就要使用第二层调用者的函数名和py文件名
        '''
        base = inspect.stack()
        # 当前的函数名
        self_func_name = base[0].function
        # 当前文件的py名
        self_py_name = base[0].filename

        # 指定调用层的调用者的函数名
        num_call_func_name = base[call_num].function
        # 指定调用层的调用者的py文件名
        num_call_py_name = base[call_num].filename
        num_call_py = os.path.basename(num_call_py_name)
        # 指定调用层的调用者对应的yml的文件名(不含路径)
        num_call_yml = num_call_py.replace('.py', '.yml')
        # 拼接指定调用层的调用者对应的yml的路径(含文件名)
        num_yml_path = os.path.join(yml_abs_dir, num_call_yml)

        with open(num_yml_path, mode='r', encoding='utf-8')as f:
            yml_datas = yaml.safe_load(f)
            call_yml_data = yml_datas.get(num_call_func_name)

        # # 返回指定调用层调用者所对应的所有的yml数据
        # return yml_datas
        # # 返回指定调用层调用者中调用方法所涉及到的yml数据
        return call_yml_data
        # # 将所有的结果都返回了
        # return yml_datas,call_yml_data

    def get_yml_data_by_method(self, call_num: int, methodname: str):
        '''
        返回指定层调用者及调用函数对应的yml数据  \n
        主要用于@pytest.mark.parametrize() 参数化  \n
        :param call_num: 第几层调用者,整数
        :param methodname: 调用者的函数名
        :return:
        '''
        # 方法二：
        '''
        如果是在Base.py文件中 调用的话，那么就要使用第二层调用者的函数名和py文件名
        '''
        base = inspect.stack()
        # 当前的函数名
        self_func_name = base[0].function
        # 当前文件的py名
        self_py_name = base[0].filename

        # 指定调用层的调用者的函数名
        # num_call_func_name = base[call_num].function
        num_call_func_name = methodname
        # 指定调用层的调用者的py文件名
        num_call_py_name = base[call_num].filename
        num_call_py = os.path.basename(num_call_py_name)
        # 指定调用层的调用者对应的yml的文件名(不含路径)
        num_call_yml = num_call_py.replace('.py', '.yml')
        # 拼接指定调用层的调用者对应的yml的路径(含文件名)
        num_yml_path = os.path.join(yml_abs_dir, num_call_yml)

        with open(num_yml_path, mode='r', encoding='utf-8')as f:
            yml_datas = yaml.safe_load(f)
            call_yml_data = yml_datas.get(num_call_func_name)

        # # 返回指定调用层调用者所对应的所有的yml数据
        # return yml_datas
        # # 返回指定调用层调用者中调用方法所涉及到的yml数据
        return call_yml_data
        # # 将所有的结果都返回了
        # return yml_datas,call_yml_data

    def get_yml_data(self,yml_dir=None)->dict:
        '''
        返回第二层调用者的调用函数对应的yml的数据  \n
        :param yml_dir: 第二层调用者,如page层 对应的yml 所在的目录,不包括data目录
        :return: dict
        '''

        # 方法二：
        '''
        如果是在Base.py文件中 调用的话，那么就要使用第二层调用者的函数名和py文件名
        '''
        base = inspect.stack()
        # 当前的函数名
        self_func_name = base[0].function
        # 当前文件的py名
        self_py_name = base[0].filename
        # 第一层调用者的函数名
        first_call_func_name = base[1].function
        # 第一层调用者的py文件名
        first_call_py_name = base[1].filename
        # 第二层调用者的函数名
        second_call_func_name = base[2].function
        # 第二层调用者的py文件名
        second_call_py_name = base[2].filename
        second_call_py = os.path.basename(second_call_py_name)
        # 设置第二层调用者对应的yml的文件名(不含路径)
        second_call_yml = second_call_py.replace('.py', '.yml')
        # 拼接第二层调用者对应的yml的路径(含文件名)
        if yml_dir == None:
            second_yml_path = os.path.join(yml_abs_dir, second_call_yml)
        else:
            second_yml_path = os.path.join(os.path.join(yml_abs_dir, yml_dir),second_call_yml)

        with open(second_yml_path, mode='r', encoding='utf-8')as f:
            yml_datas = yaml.safe_load(f)
            call_yml_data = yml_datas.get(second_call_func_name)

        # # 返回第二层调用者所对应的所有的yml数据
        # return yml_datas
        # # 返回第二层调用者中调用方法所涉及到的yml数据
        return call_yml_data
        # # 将所有的结果都返回了
        # return yml_datas,call_yml_data
